export default class ChineseNumber {
  private static readonly chars: string[] = [
    "零",
    "一",
    "二",
    "三",
    "四",
    "五",
    "六",
    "七",
    "八",
    "九",
  ];
  private static readonly decimals: string[] = ["", "万", "亿"];
  private static readonly units: string[] = ["", "十", "百", "千"];
  private static readonly map = {
    零: "零",
    一: "壹",
    二: "贰",
    三: "叁",
    四: "肆",
    五: "伍",
    六: "陆",
    七: "柒",
    八: "捌",
    九: "玖",
    十: "拾",
    百: "佰",
    千: "仟",
    万: "万",
    亿: "亿",
  };
  private static readonly numberMap = {
    零: 0,
    壹: 1,
    贰: 2,
    叁: 3,
    肆: 4,
    伍: 5,
    陆: 6,
    柒: 7,
    捌: 8,
    玖: 9,
    十: 10,
    百: 100,
    千: 1000,
    万: 10000,
    亿: 100000000,
  };
  private _int: string;
  private _dec: string;
  private _sym: string = "";
  constructor(strNum: string | number) {
    if (typeof strNum === "number") {
      if (strNum === 0) {
        this._int = "零";
        this._dec = "";
        return;
      }
      if (strNum < 0) {
        this._sym = "负";
        strNum = -strNum;
      }
    } else if (typeof strNum === "string" && Number(strNum)) {
      if (strNum.indexOf("-") > -1) {
        this._sym = "负";
        strNum = strNum.replace("-", "");
      } else if (strNum.indexOf("+") > -1) {
        strNum = strNum.replace("+", "");
      }
    } else {
      this._int = "";
      this._dec = "";
      return;
    }
    const ss = strNum.toString();
    if (ss.indexOf(".") > -1) {
      const [int, dec] = ss.split(".");
      this._int = int;
      this._dec = dec;
    } else {
      this._int = ss;
      this._dec = "";
    }
  }

  public static toChinese(num: number) {
    if (num === 0) return this.chars[0];
    let sym = "";
    if (num < 0) {
      sym = "负";
      num = -num;
    }
    const ss = num.toString();
    if (ss.indexOf(".") > -1) {
      throw new Error("不支持小数!");
    }
    const ints = ss.replace(/\B(?=(\d{4})+$)/g, ",").split(",");
    let result = "";
    for (let i = 0, len = ints.length; i < len; i++) {
      const c = this._transform(ints[i]);
      let u = this.decimals[len - 1 - i];
      if (c === this.chars[0]) {
        u = "";
      }
      result += c + u;
    }
    result = this._handleZero(result);
    result = sym + result;
    return result;
  }

  private static _handleZero(str: string) {
    return str.replace(/零{2,}/g, "零").replace(/零+$/g, "");
  }

  private static _transform(strNum: string) {
    if (strNum === "0000") {
      return this.chars[0];
    }
    let res = "";
    for (let i = 0, len = strNum.length; i < len; i++) {
      const c = this.chars[+strNum[i]];
      let u = this.units[len - 1 - i];
      if (c === this.chars[0]) {
        u = "";
      }
      res += c + u;
    }
    res = this._handleZero(res);
    return res;
  }
}
